package gui;

import java.io.IOException;
import java.util.LinkedList;
import java.util.List;

import org.primefaces.context.RequestContext;

import database.DatabaseManager;
import database.SpaceTrackLogin;

import user.User;
import user.UserManager;
import utils.ApplicationPreferences;
import utils.CurrentUser;
import utils.InvalidInputException;
import utils.PasswordGenerator;
import utils.UserNotFoundException;
import utils.Validator;

public class adminOptionsBean {

	private String newUsername;
	private String newUserPassword;
	private List<User> users;
	private User selectedUser;
	private List<String> usernames;
	private String selectedUsername;
	private String newResetPassword;

	private String dbUrl;
	private String dbName;
	private String dbUsername;
	private String dbPass;

	private String spaceTrackUsername;
	private String spaceTrackPassword;

	private int maxSimulations;

	public adminOptionsBean() {
		UserManager usermanager = UserManager.getInstance();
		users = usermanager.getUsers();
		// Make a list of all usernames
		usernames = new LinkedList<String>();
		for (int i = 0; i < users.size(); i++) {
			usernames.add(users.get(i).getName());
		}
	}

	public String getNewUsername() {
		return newUsername;
	}

	public void setNewUsername(String newUsername) {
		this.newUsername = newUsername;
	}

	public String getNewUserPassword() {
		return newUserPassword;
	}

	public List<User> getUsers() {
		return users;
	}

	public User getSelectedUser() {
		return selectedUser;
	}

	public void setSelectedUser(User selectedUser) {
		this.selectedUser = selectedUser;
	}

	public String getSelectedUsername() {
		return selectedUsername;
	}

	public void setSelectedUsername(String selectedUsername) {
		this.selectedUsername = selectedUsername;
	}

	public List<String> getUsernames() {
		return usernames;
	}

	public String getNewResetPassword() {
		return newResetPassword;
	}

	/**
	 * Returns current database URL
	 * 
	 * @return database URL
	 */
	public String getDbUrl() {
		ApplicationPreferences appPref = ApplicationPreferences.getInstance();
		return appPref.getDbURL();
	}

	public void setDbUrl(String dbUrl) {
		this.dbUrl = dbUrl;
	}

	/**
	 * Returns current database name
	 * 
	 * @return database name
	 */
	public String getDbName() {
		ApplicationPreferences appPref = ApplicationPreferences.getInstance();
		return appPref.getDbName();
	}

	public void setDbName(String dbName) {
		this.dbName = dbName;
	}

	/**
	 * Returns current username for database
	 * 
	 * @return username for database
	 */
	public String getDbUsername() {
		ApplicationPreferences appPref = ApplicationPreferences.getInstance();
		return appPref.getDbUsername();
	}

	public void setDbUsername(String dbUsername) {
		this.dbUsername = dbUsername;
	}

	/**
	 * Returns current password for database
	 * 
	 * @return database password
	 */
	public String getDbPass() {
		ApplicationPreferences appPref = ApplicationPreferences.getInstance();
		return appPref.getDbPass();
	}

	public void setDbPass(String dbPass) {
		this.dbPass = dbPass;
	}

	/**
	 * Returns currently set max amount of concurrent simulations
	 * 
	 * @return max amount of concurrent simulations
	 */
	public int getMaxSimulations() {
		ApplicationPreferences appPref = ApplicationPreferences.getInstance();
		return appPref.getMaxConcurrentSims();
	}

	public void setMaxSimulations(int maxSimulations) {
		this.maxSimulations = maxSimulations;
	}

	/**
	 * Returns current username for SpaceTrack
	 * 
	 * @return username for SpaceTrack
	 */
	public String getSpaceTrackUsername() {
		ApplicationPreferences appPref = ApplicationPreferences.getInstance();
		if (appPref.getSourceDBs().get(0) != null) {
			return appPref.getSourceDBs().get(0).getUsername();
		}
		return null;
	}

	public void setSpaceTrackUsername(String spaceTrackUsername) {
		this.spaceTrackUsername = spaceTrackUsername;
	}

	/**
	 * Returns current password for SpaceTrack
	 * 
	 * @return password for SpaceTrack
	 */
	public String getSpaceTrackPassword() {
		ApplicationPreferences appPref = ApplicationPreferences.getInstance();
		if (appPref.getSourceDBs().get(0) != null) {
			return appPref.getSourceDBs().get(0).getPassword();
		}
		return null;
	}

	public void setSpaceTrackPassword(String spaceTrackPassword) {
		this.spaceTrackPassword = spaceTrackPassword;
	}

	/**
	 * Displays a dialog for deleting a user
	 */
	public void showDeleteUserDialog() {
		// Check if user is admin
		if (CurrentUser.getCurrentUser().isAdmin()) {
			RequestContext context = RequestContext.getCurrentInstance();
			context.execute("deleteUserDialog.show()");
		} else {
			// If user is not admin, show error message
			MessageController messageController = new MessageController();
			messageController
					.showErrorMessage("Nur der Administrator hat den Zugriff auf diese Funktion!");
		}
	}

	/**
	 * Display a confirm dialog for deleting a user
	 */
	public void showDeleteConfirm() {
		RequestContext context = RequestContext.getCurrentInstance();
		context.execute("confirmDeleteDialog.show()");
	}

	/**
	 * Deletes a user from database
	 */
	public void deleteUser() {
		UserManager userManager = UserManager.getInstance();
		MessageController msgController = new MessageController();
		// Find the User object with selected username
		if (!selectedUsername.equals(CurrentUser.getCurrentUsername())) {
			userManager.deleteUser(selectedUsername);
		} else {
			msgController
					.showErrorMessage("Sie können nicht sich selbst löschen!");
		}
		// Update the lists
		users = userManager.getUsers();
		// Refresh the usernames' list
		usernames.clear();
		for (int i = 0; i < users.size(); i++) {
			usernames.add(users.get(i).getName());
		}
		// reset global values
		selectedUsername = null;
		selectedUser = null;
	}

	/**
	 * Displays a dialog for resetting a password
	 */
	public void showResetPasswordDialog() {
		// Check if user is admin
		if (CurrentUser.getCurrentUser().isAdmin()) {
			RequestContext context = RequestContext.getCurrentInstance();
			context.execute("resetPasswordDialog.show()");
		} else {
			// If user is not admin, display error message
			MessageController messageController = new MessageController();
			messageController
					.showErrorMessage("Nur der Administrator hat den Zugriff auf diese Funktion!");
		}
	}

	/**
	 * Resets user's password
	 * 
	 * @throws InvalidInputException
	 * @throws UserNotFoundException
	 */
	public void resetPassword() throws InvalidInputException,
			UserNotFoundException {
		UserManager userManager = UserManager.getInstance();
		PasswordGenerator pwGen = new PasswordGenerator();
		// Generate new password
		newResetPassword = pwGen.generate(8);
		// Set new password for user
		userManager.getUser(selectedUsername).setPassword(newResetPassword);
		// Show dialog containing new generated password
		RequestContext context = RequestContext.getCurrentInstance();
		context.execute("resetPasswordDetailsDialog.show()");
	}

	/**
	 * Displays a dialog for adding a new user
	 */
	public void showNewUserDialog() {
		// Check if user is admin
		if (CurrentUser.getCurrentUser().isAdmin()) {
			RequestContext context = RequestContext.getCurrentInstance();
			context.execute("newUserDialog.show()");
		} else {
			// If user is not admin, display error message
			MessageController messageController = new MessageController();
			messageController
					.showErrorMessage("Nur der Administrator hat den Zugriff auf diese Funktion!");
		}
	}

	/**
	 * Creates a new user and stores it in database
	 * 
	 * @throws InvalidInputException
	 * @throws UserNotFoundException
	 */
	public void createNewUser() throws InvalidInputException,
			UserNotFoundException {
		RequestContext context = RequestContext.getCurrentInstance();
		MessageController messageController = new MessageController();
		UserManager userManager = UserManager.getInstance();
		if (newUsername.isEmpty()) {
			messageController.showErrorMessage("Benutzername fehlt!");
			return;
		}
		if (!(Validator.isValidUsername(newUsername))) {
			messageController.showErrorMessage("Benutzername ungültig!");
			return;
		}
		if (userManager.isExistingUser(newUsername)) {
			messageController.showErrorMessage("Benutzer existiert schon!");
			return;
		} else {
			// Hide the dialog
			context.execute("newUserDialog.hide()");
			// Create new user with gives username;
			userManager.createUser(newUsername);
			// Fetch the generated password of the new user
			newUserPassword = userManager.getUser(newUsername).getPassword();
			usernames.add(newUsername);
			users.add(userManager.getUser(newUsername));
			// Show dialog containing new user's password
			context.execute("newUserDetailsDialog.show()");
		}
	}

	/**
	 * Displays a dialog for changing the database settings
	 */
	public void showDatabaseDialog() {
		// Check if user is admin
		if (CurrentUser.getCurrentUser().isAdmin()) {
			RequestContext context = RequestContext.getCurrentInstance();
			context.execute("databaseSettingsDialog.show()");
		} else {
			// If user is not admin, display error message
			MessageController messageController = new MessageController();
			messageController
					.showErrorMessage("Nur der Administrator hat den Zugriff auf diese Funktion!");
		}
	}

	/**
	 * Edits the database settings
	 */
	public void editDatabaseSettings() {
		ApplicationPreferences appPref = ApplicationPreferences.getInstance();
		// Save the database settings
		appPref.setDatabase(dbUrl, dbName, dbUsername, dbPass);
		RequestContext context = RequestContext.getCurrentInstance();
		// Close dialog
		context.execute("databaseSettingsDialog.hide()");
	}

	/**
	 * Displays a dialog for setting the max. amount of concurrent simulations
	 */
	public void showMaxSimDialog() {
		// Check if user is admin
		if (CurrentUser.getCurrentUser().isAdmin()) {
			RequestContext context = RequestContext.getCurrentInstance();
			context.execute("concurrentSimDialog.show()");
		} else {
			// If user is not admin, display error message
			MessageController messageController = new MessageController();
			messageController
					.showErrorMessage("Nur der Administrator hat den Zugriff auf diese Funktion!");
		}
	}

	/**
	 * Sets the max ammount of concurrent simulations
	 */
	public void setMaxSim() {
		ApplicationPreferences appPref = ApplicationPreferences.getInstance();
		// Save max amount of simulations in preferences
		appPref.setMaxConcurrentSims(maxSimulations);
		RequestContext context = RequestContext.getCurrentInstance();
		// Close dialog
		context.execute("concurrentSimDialog.hide()");
	}

	/**
	 * Displays the dialog for editing login data of source databases
	 */
	public void showSourceDBDialog() {
		// Check if user is admin
		if (CurrentUser.getCurrentUser().isAdmin()) {
			RequestContext context = RequestContext.getCurrentInstance();
			context.execute("editSourceDBDialog.show()");
		} else {
			// If user is not admin, display error message
			MessageController messageController = new MessageController();
			messageController
					.showErrorMessage("Nur der Administrator hat den Zugriff auf diese Funktion!");
		}
	}

	/**
	 * Sets the login information for source databases
	 * 
	 * @throws IOException
	 */
	public void setSourceDBLogins() throws IOException {
		MessageController messageController = new MessageController();
		ApplicationPreferences appPref = ApplicationPreferences.getInstance();
		if (spaceTrackUsername.isEmpty()) {
			messageController
					.showErrorMessage("SpaceTrack Benutzername fehlt!");
			return;
		}
		if (spaceTrackPassword.isEmpty()) {
			messageController.showErrorMessage("SpaceTrack Passwort fehlt!");
			return;
		}
		if (!(new SpaceTrackLogin(spaceTrackUsername, spaceTrackPassword)
				.isCorrectLogin())) {
			messageController
					.showErrorMessage("SpaceTrack Logindaten sind ungültig!");
			return;
		}
		// Save SpaceTrack login data
		appPref.addSourceDB(spaceTrackUsername, spaceTrackPassword, 0);
		// Close dialog
		RequestContext context = RequestContext.getCurrentInstance();
		context.execute("editSourceDBDialog.hide()");

	}

}
